#ifndef TRACE_H
#define TRACE_H

#include <vector>
#include "cursor.h"
#include "filter.h"

#define ONLINE  0
#define OFFLINE 1

using namespace std;

class Trace{
    private:
        int id;
        bool online;
        vector<Cursor> cursors;
        vector<Filter*> onlineFilters;
        vector<Filter*> offlineFilters;        
        
    public:
        Trace(){
            this->id = 0; 
            online=false;
        }
        
        Trace(int id){
            this->id = id;
        }
        
        ~Trace(){cursors.clear();onlineFilters.clear();offlineFilters.clear();}
        
        
        void setId(int id){
            this->id = id;
        }
        
        int getId(){
            return this->id;        
        }
        
        bool isEmpty(){
            return this->cursors.empty();
        }
        
        Cursor& operator[](int i){
            if (i >= 0){
                return this->cursors[i];
            }
            else{
                return this->cursors[this->size() + i];
            }
        }
        
        unsigned int size(){
            return this->cursors.size();
        }
        
        void erase(int i){
            this->cursors.erase(this->cursors.begin()+i);
        }     
        
        void erase(int b, int e){
            if ( b >= 0 and b < e and e < this->cursors.size())
            for (int i = b; i < e; i++){
                this->cursors.erase(this->cursors.begin()+b);
            }
        }              
        
        void clear(){
            this->cursors.clear();
        }
        
        void addCursor(Cursor &c){
            bool insert = true;
            if (online){
                for (unsigned int i=0; i<onlineFilters.size(); i++ ){
                    insert = insert and onlineFilters[i]->isCursor(c);
                }
            }
            if (insert){
                this->cursors.push_back(c);
            }
        }
        
        vector<Cursor> &getCursors(){
            return this->cursors;
        }
        
        void addFilter(Filter *filter, int category=ONLINE){
            if (category == ONLINE){
                this->onlineFilters.push_back(filter);
                online = true;
            }
            else{
                this->offlineFilters.push_back(filter);
            }
        }
        
        void removeFilter(int type){
            for (unsigned int i=0; i<onlineFilters.size(); i++ ){
                if (onlineFilters[i]->getId() == type) 
                    onlineFilters.erase(onlineFilters.begin()+i);
            }
            for (unsigned int i=0; i<offlineFilters.size(); i++ ){
                if (offlineFilters[i]->getId() == type) 
                    offlineFilters.erase(offlineFilters.begin()+i);
            }
        }
        
        void filter(){
            for (unsigned int i=0; i<offlineFilters.size(); i++ ){
                offlineFilters[i]->filtering( cursors ); 
            }
        }
};

class TraceFactory{
    public:
        virtual Trace createTrace(int id){}
};

#endif /* TRACE_H */
